package us.gaaoc.framework.webapp.backingbeans.profile;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.faces.component.html.HtmlInputHidden;
import javax.faces.component.html.HtmlInputText;
import javax.faces.component.html.HtmlInputTextarea;
import javax.faces.context.FacesContext;

import org.apache.myfaces.custom.fileupload.HtmlInputFileUpload;
import org.apache.myfaces.custom.fileupload.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;

import us.gaaoc.framework.model.CaseRecord;
import us.gaaoc.framework.model.CaseRecordIdExternalCaseRecordNumber;
import us.gaaoc.framework.model.Court;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonParticipants;
import us.gaaoc.framework.model.Roles;
import us.gaaoc.framework.webapp.backingbeans.BaseBackingBean;
import us.gaaoc.framework.webapp.util.Sender;

/**
 * This class serves as the error reporter for the GAJE project.  Users
 * can submit issues related to particular cases to JIRA with a simplified web
 * form interface.  This is accomplished by using the SOAP web service built
 * into JIRA.
 * 
 * @author Brandon Denney
 * @date 2008-07-17
 * @version GAJE 2.x
 */
public class Help extends BaseBackingBean {
	
	/* **************** *
	 * Global Variables *
	 * **************** */
	/** Default Serial Version UID */
	private static final long serialVersionUID = 235987L;
	/** Place-holder for the OCSS Number Input UI Element. */
	private HtmlInputText OCSSNumberInputText;
	/** Place-holder for the Civil Action Number Input UI Element. */
	private HtmlInputText civilActionNumberInputText;
	/** Place-holder for the Defendant Name Input UI Element. */
	private HtmlInputText defendantNameInputText;
	/** Place-holder for the User Description Input UI Element. */
	private HtmlInputTextarea descriptionInputTextarea;
	/** Place-holder for the hidden Uuid Input UI Element. */
	private HtmlInputHidden uuidInputHidden;
	/** The problem case's OCSS Number. */
	private static String OCSSNumber;
	/** The problem case's Civil Action Number */
	private static String civilActionNumber;
	/** The problem case's Defendant Name. */
	private static String defendantName;
	/** The problem case's user description. */
	private static String description;
	/** The problem case's case record uuid. */
	private static String uuid;
	/** Flag indicating if the auto-populate warning should be displayed. */
	private static boolean displayAutoPopulateWarning = false;
	/** Place holder for an uploaded file -- Feature not implemented. */
	private UploadedFile attachment;
	/** Place holder for an uploaded file's binary. -- Feature not implemented.*/
	private byte[] attachmentBinary;
	/** Place holder for the Html file upload input. -- Feature not implemented.*/
	private HtmlInputFileUpload attachmentInputFileUpload;
	/** The session map for the application. */
	@SuppressWarnings("unchecked")
	private Map sessionMap;
	
	@Autowired
	private Sender sender;
	@Autowired
	Properties gajeProperties;
	
	/* ******* *
	 * Getters *
	 * ******* */
	/**
	 * Getter for the OCSSNumber String.
	 * 
	 * @return the problem case's OCSS Number.
	 */
	public String getOCSSNumber() {
		return OCSSNumber;
	}
	
	/**
	 * Getter for the CivilActionNumber String.
	 * 
	 * @return the problem case's Civil Action Number.
	 */
	public String getCivilActionNumber() {
		return civilActionNumber;
	}
	
	/**
	 * Getter for the DefendantName String.
	 * 
	 * @return the problem case's defendant's name.
	 */
	public String getDefendantName() {
		return defendantName;
	}
	
	/**
	 * Getter for the Description String.
	 * 
	 * @return the problem case's user description.
	 */
	public String getDescription() {
		return description;
	}
	
	/**
	 * Getter for the Uuid.
	 * 
	 * @return the problem case's uuid.
	 */
	public String getUuid() {
		return uuid;
	}
	
	/**
	 * Getter for the OCSSNumberInputText UI Element.
	 * 
	 * @return the UI Element linked to the OCSSNumber String.
	 */
	public HtmlInputText getOCSSNumberInputText() {
		return OCSSNumberInputText;
	}
	
	/**
	 * Getter for the CivilActionNumberInputText UI Element.
	 * 
	 * @return the UI Element linked to the CivilActionNumber String.
	 */
	public HtmlInputText getCivilActionNumberInputText() {
		return civilActionNumberInputText;
	}

	/**
	 * Getter for the DefendantNameInputText UI Element.
	 * 
	 * @return the UI Element linked to the DefendantName String.
	 */
	public HtmlInputText getDefendantNameInputText() {
		return defendantNameInputText;
	}

	/**
	 * Getter for the DescriptionInputTextArea UI Element.
	 * 
	 * @return the UI Element linked to the user description String.
	 */
	public HtmlInputTextarea getDescriptionInputTextarea() {
		return descriptionInputTextarea;
	}
	
	/**
	 * Getter for the UuidInputHidden UIElement.
	 * 
	 * @return the UI Element linked to the hidden case record uuid.
	 */
	public HtmlInputHidden getUuidInputHidden() {
		return uuidInputHidden;
	}
	
	/**
	 * Getter for the DisplayAutoPopulateWarning flag. 
	 * 
	 * @return the flag indicating if the form was auto populated or not.
	 */
	public boolean getDisplayAutoPopulateWarning() {
		return displayAutoPopulateWarning;
	}
	
	/**
	 * Getter for the attachment UploadedFile. This feature is not implemented.
	 * 
	 * @return the problem case's file attachment.
	 */
	public UploadedFile getAttachment() {
		return attachment;
	}
	
	/**
	 * Getter for the AttachmentBinary byte array. This feature is not 
	 * implemented.
	 * 
	 * @return the binary for the attached file.
	 */
	public byte[] getAttachmentBinary() {
		return attachmentBinary;
	}
	
	/**
	 * Getter for the AttachmentInputFileUpload UI Element.  This feature is
	 * not implemented.
	 * 
	 * @return the UI Element linked with the attachment file.
	 */
	public HtmlInputFileUpload getAttachmentInputFileUpload() {
		return attachmentInputFileUpload;
	}
	
	/**
	 * Getter for the application session map.
	 * 
	 * @return the session map for the application.
	 */
	@SuppressWarnings("unchecked")
	public Map getSessionMap() {
		this.sessionMap = this.getFacesContext().getExternalContext()
			.getSessionMap();
		return this.sessionMap;
	}
	
	/* ******* *
	 * Setters *
	 * ******* */
	/**
	 * Setter for the OCSSNumber String.
	 * 
	 * @param ocss the problem case's OCSS number.
	 */
	public void setOCSSNumber(String ocss) {
		OCSSNumber = ocss;
	}
	
	/**
	 * Setter for the CivilActionNumber String.
	 * 
	 * @param civil the problem case's civil action number.
	 */
	public void setCivilActionNumber(String civil) {
		civilActionNumber = civil;
	}
	
	/**
	 * Setter for the DefendantName String.
	 * 
	 * @param name the problem case's defendant's name.
	 */
	public void setDefendantName(String name) {
		defendantName = name;
	}
	
	/**
	 * Setter for the user Description String.
	 * 
	 * @param prose the problem case's user description of the problem.
	 */
	public void setDescription(String prose) {
		description = prose;
	}
	
	/**
	 * Setter for the case record Uuid.
	 * 
	 * @param id the problem case's case record uuid.
	 */
	public void setUuid(String id) {
		uuid = id;
	}
	
	/**
	 * Setter for the OCSSNumberInputText UI Element.
	 * 
	 * @param oCSSNumberInputText the UI Element linked to the OCSSNumber 
	 * String.
	 */
	public void setOCSSNumberInputText(HtmlInputText oCSSNumberInputText) {
		OCSSNumberInputText = oCSSNumberInputText;
	}
	
	/**
	 * Setter for the CivilActionNumberInputText UI Element.
	 * 
	 * @param civilActionNumberInputText the UI Element linked to the 
	 * CivilActionNumber String.
	 */
	public void setCivilActionNumberInputText(HtmlInputText civilActionNumberInputText) {
		this.civilActionNumberInputText = civilActionNumberInputText;
	}
	
	/**
	 * Setter for the DefendantNameInputText UI Element.
	 * 
	 * @param defendantNameInputText the UI Element linked to the
	 * DefendantName String.
	 */
	public void setDefendantNameInputText(HtmlInputText defendantNameInputText) {
		this.defendantNameInputText = defendantNameInputText;
	}
	
	/**
	 * Setter for the DescriptionInputTextArea UI Element.
	 * 
	 * @param descriptionInputTextarea the UI Element linked to the user
	 * description of the problem.
	 */
	public void setDescriptionInputTextarea(HtmlInputTextarea descriptionInputTextarea) {
		this.descriptionInputTextarea = descriptionInputTextarea;
	}
	
	/**
	 * Setter for the UuidInputHidden UI Element.
	 * 
	 * @param uuidInputHidden the UI Element linked to the user Description 
	 * String.	 
	 */
	public void setUuidInputHidden(HtmlInputHidden uuidInputHidden) {
		this.uuidInputHidden = uuidInputHidden;
	}
	
	/**
	 * Setter for the DisplayAutoPopulateWarning flag.
	 * 
	 * @param displayAutoPopulateWarning the flag indicating if the form has
	 * been auto-populated.
	 */
	public void setDisplayAutoPopulateWarning(
			boolean displayAutoPopulateWarning) {
		Help.displayAutoPopulateWarning = displayAutoPopulateWarning;
	}
	
	/**
	 * Setter for the Attachment UploadedFile. This feature is not implemented.
	 * 
	 * @param attachment the problem case's related file.
	 */
	public void setAttachment(UploadedFile attachment) {
		this.attachment = attachment;
	}
	
	/**
	 * Setter for the AttachmentBinary byte array. This feature is not 
	 * implemented.
	 * 
	 * @param attachmentBinary the problem case's file binary.
	 */
	public void setAttachmentBinary(byte[] attachmentBinary) {
		this.attachmentBinary = attachmentBinary;
	}
	
	/**
	 * Setter for the AttachmentInputFileUpload UI Element. This feature is not
	 * implemented.
	 * 
	 * @param attachmentInputFileUpload the UI Element linked to the Attachment
	 * UploadedFile.
	 */
	public void setAttachmentInputFileUpload(HtmlInputFileUpload 
			attachmentInputFileUpload) {
		this.attachmentInputFileUpload = attachmentInputFileUpload;
	}

	/**
	 * Setter for the application's session map.
	 * 
	 * @param sessionMap the application's session map.
	 */
	@SuppressWarnings("unchecked")
	public void setSessionMap(Map sessionMap) {
		this.sessionMap = sessionMap;
	}
	
	/**
	 * Default Constructor.  Checks to see if this page was reached from the
	 * case record details page.  If so, the form is auto-populated, and the
	 * auto-populate warning is displayed.
	 */
	@SuppressWarnings("unchecked")
	public Help() {
		
		String caseUuid = null;
		
		Set keys = getSessionMap().keySet();
	
		/*
		 * If the session map contains a caseUuid, then this page was reached
		 * from the case record details page.  If it was not, then form values
		 * are cleared to ensure that old data is not loaded into the form.
		 */
		if(keys.contains("from") && keys.contains("caseUuid")) {
			setDisplayAutoPopulateWarning(true);
			caseUuid = (String)sessionMap.get("caseUuid");
			setUuid(caseUuid);
			populateForm(caseUuid);
		}
		else {
			setDisplayAutoPopulateWarning(false);
			setUuid("");
			clear();
		}
	}
	
	/**
	 * This method auto-populates the form with data from the case record
	 * matching the passed case record uuid.
	 * 
	 * @param caseUuid the uuid of the case record that was just viewed with
	 * the case details page.
	 */
	public void populateForm(String caseUuid) {
		
		String courtUuid = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("courtUuid");
		
		CaseRecord caseRecord = (CaseRecord)this.getModelFacade()
			.findCaseRecordById(caseUuid, courtUuid);
		
		//Set defendant name, if it exists.
		List<PersonParticipants> caseParticipantList = caseRecord.getPersonParticipants();
		
		for(PersonParticipants pp : caseParticipantList) {
			if(pp.getRelationship().getCode() == 2) {
				setDefendantName(
						pp.getPerson().getFirstName() +
						" " +
						pp.getPerson().getMiddleName() +
						" " +
						pp.getPerson().getLastName());
			}
		}
		
		//Set OCSS number, if it exists.
		CaseRecordIdExternalCaseRecordNumber caseOCSSNumber =
				this.getModelFacade().findExternalCaseRecordNumbers(caseUuid).get(0);
		
		if(caseOCSSNumber != null) {
			setOCSSNumber(caseOCSSNumber.getExternalCaseRecordNumber());
		}
		
		//Set Civil Action Number, if it exists.
		setCivilActionNumber(caseRecord.getCaseTrackingId());
		
		//Clean up session map to prevent incorrect auto-population.
		getSessionMap().remove("caseUuid");
	}
	
	/**
	 * This method reads the values of the fields on the error reporting page, 
	 * and sends the issue to JIRA using the JiraSoapClient.
	 * 
	 * @return the navigation string to return the user to their dashboard.
	 */
	public String onSubmit() {
		
		//Read the fields of the page.
		OCSSNumber = OCSSNumberInputText.getValue().toString();
		civilActionNumber = civilActionNumberInputText.getValue().toString();
		defendantName = defendantNameInputText.getValue().toString();
		description = descriptionInputTextarea.getValue().toString();
		
		//Add information to the description.
		Person reporter = (Person)getSessionMap().get("person");
		String courtUuid = (String)getSessionMap().get("courtUuid");
		Court court = this.getModelFacade().findCourtByUuid(courtUuid);
		
		description += "\n\n Thanks ";
		
		description += "\n\n " + reporter.getFirstName()+ " " + reporter.getLastName();
		
		description += "\n\n " + court.getName();

		
		System.out.println(description);
		DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        Date date = new Date();	  
        
		SimpleMailMessage msg=new SimpleMailMessage();       	
       	msg.setTo(gajeProperties.getProperty("mail.recipient").split(";"));       
		msg.setFrom(gajeProperties.getProperty("mail.sender"));
		msg.setSubject("OCSS Number: "+ OCSSNumber + " Civil Action Number " + civilActionNumber +" Defendant Name: " + defendantName);
		
		sender.send(msg, null, null, description);

		//Send the issue to JIRA
		//JiraSoapClient soapRequest = new JiraSoapClient();
		//soapRequest.createIssue(OCSSNumber,	civilActionNumber, defendantName, description, uuid);
		
		//The following navigates the user to their respective home dashboards.
		Person user = (Person)this.getFacesContext()
			.getExternalContext().getSessionMap().get("person");
		List<Roles> personRoles = user.getRoles();
		String navigationString = "";
		
		for(Roles r : personRoles) {
			if (r.getRole().contains("admin")) {
				navigationString = "adminDashboard";
			} else if (r.getRole().contains("clerk")) {
				navigationString = "clerkDashboard";
			} else if (r.getRole().equals("public")) {
				navigationString = "publicDashboard";
			} else if (r.getRole().equals("agent")) {
				navigationString = "agentDashboard";
			} else if (r.getRole().equals("attorney")) {
				navigationString = "attorneyDashboard";
			} else if(r.getRole().contains("judge")) {
				navigationString = "judgeDashboard";
			}
		}
		 
		return navigationString;
	}
	
	/**
	 * This method clears the form.
	 */
	public void clear() {
		setCivilActionNumber("");
		setDefendantName("");
		setOCSSNumber("");
		setUuid("");
	}

	public Sender getSender() {
		return sender;
	}

	public void setSender(Sender sender) {
		this.sender = sender;
	}

	public Properties getGajeProperties() {
		return gajeProperties;
	}

	public void setGajeProperties(Properties gajeProperties) {
		this.gajeProperties = gajeProperties;
	}
	
}
